/*
 * BaseDAO.java
 *
 * $Id: BaseDAO.java,v 1.1 2008-03-18 12:58:46 mario Exp $
 */
package org.ceteca.explica.server.common;

import java.util.ArrayList;
import java.util.List;

import org.ceteca.explica.core.ExplicaException;
import org.ceteca.explica.core.InterfaceErrors;
import org.ceteca.explica.core.common.ValueOT;
import org.ceteca.explica.core.util.ResultMessage;
import org.ceteca.explica.core.util.ResultMessageCatalog;
import org.ceteca.explica.server.util.db.CriteriaBean;
import org.ceteca.explica.server.util.db.HibernateUtil;
import org.ceteca.explica.server.util.db.InterfaceDB;
import org.ceteca.explica.server.util.db.SQLGenerator;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.transform.Transformers;

/**
 * This class implements the general application data access object. It's 
 * a part of the data access layer and gives access to the database data.
 * It implements generic methods for accessing database data.
 * It knows the database structure and implementation. 
 * <br/>
 * This class is implemented to access a PostgreSQL database implementation.
 * <br/>
 * Responsibilities:
 * <ul>
 * 	<li> Provide statements for general querying of the elements of the database. </li>
 * </ul>
 * <br/>
 * @author Mario García García <mario@imagos.es>
 * Copyright (c) 2007 Fundación Centro Tecnolóxico da Carne
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <br/>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <br/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class BaseDAO {
	/**
	 * Instance of ResultMessageCatalog that will be used to
	 * report any error during the DAO operations.
	 */
	private ResultMessageCatalog msgCatalog;
	
	/**
	 * Default constructor of the BaseDAO class.
	 * @param msgCatalog ResultMessageCatalog, instance of the catalog of result
	 * messages available for reporting any error during the DAO operations.
	 */
	public BaseDAO(ResultMessageCatalog msgCatalog) {
		this.msgCatalog = msgCatalog;
	}

	/**
	 * Returns all the elements stored in a database table. Returns only the internal
	 * identifier (key) of each element.
	 * @param tableName String, name of the database table to be queried.
	 * @param idfieldName String, name of the internal identifier field
	 * of the table.
	 * @return List, list of elements contained in the table.
	 * @throws ExplicaException, in case any error ocurrs during the query.
	 */
	public List getTableIds(String tableName, String idfieldName) throws ExplicaException {
		List result = new ArrayList();
		// Open a new Hibernate session to query the Database
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		SQLGenerator sqlGen = new SQLGenerator();
		
		String sqlQuery = null;

        try {
        	// Create the list of fields to include in the resulting query
        	ArrayList lFields = new ArrayList();
        	lFields.add(idfieldName);
        	
        	// Run the query and get the resulting elements
        	sqlQuery = sqlGen.getSQLQuery(tableName, lFields, null, null);
        	result = session.createSQLQuery(sqlQuery).list();
        	
            System.out.println( "Consulta realizada! " +
            		result == null || result.size() <= 0?(" No se ha encontrado ningún recurso!"):
            		("Se han encontrado: " + result.size() + " recursos"));
        }
        catch (HibernateException ex) {
        	ArrayList lParams = new ArrayList();
        	lParams.add(sqlQuery);
        	ResultMessage msg = msgCatalog.newResultMessage(InterfaceErrors.ERR_DB_QUERY_ERROR, ex, lParams);
        	throw new ExplicaException(msg);
        }
        
        // Close the Hibernate session
        session.close();	
        
        // Return the result of the query
        return result;
    }
	
	/**
	 * Returns all the elements stored in a database table. Returns a list
	 * of pairs key-value with the id of each element and its value (the
	 * description of the element that will be showed to the user on the screen).
	 * @param tableName String, name of the database table to be queried.
	 * @param idfieldName String, name of the internal identifier field
	 * of the table.
	 * @param valfieldName String, name of the value field of the table.
	 * @return List, list of elements contained in the table.
	 * @throws ExplicaException, in case any error ocurrs during the query.
	 */
	public List getTableElements(String tableName, String idfieldName, String desfieldName) 
			throws ExplicaException {
		List result = new ArrayList();
		// Open a new Hibernate session to query the Database
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		SQLGenerator sqlGen = new SQLGenerator();
		
		String sqlQuery = null;

        try {
        	// Create the list of fields to include in the resulting query
        	ArrayList lFields = new ArrayList();
        	lFields.add(idfieldName);
        	lFields.add(desfieldName);
        	
        	// Open a new SQL query to get the resulting elements.
        	sqlQuery = sqlGen.getSQLQuery(tableName, lFields, null, null);
	        SQLQuery sqlQ = session.createSQLQuery(sqlQuery);
        	
        	// Add the types of the selected fields.
	        sqlQ.addScalar(idfieldName, Hibernate.LONG);
	        sqlQ.addScalar(desfieldName, Hibernate.STRING);
	        
	        // Add the transformer to load the results of the query into the Transfer Object specified. 
	        sqlQ.setResultTransformer(Transformers.aliasToBean(ValueOT.class));
	        
	        // Run the query
	        result = sqlQ.list();
	        
            System.out.println( "Consulta realizada! " +
            		result == null || result.size() <= 0?(" No se ha encontrado ningún recurso!"):
            		("Se han encontrado: " + result.size() + " recursos"));
        }
        catch (HibernateException ex) {
        	ArrayList lParams = new ArrayList();
        	lParams.add(sqlQuery);
        	ResultMessage msg = msgCatalog.newResultMessage(InterfaceErrors.ERR_DB_QUERY_ERROR, ex, lParams);
        	throw new ExplicaException(msg);
        }
        
        // Close the Hibernate session
        session.close();	
        
        // Return the result of the query
        return result;
    }
	
	/**
	 * Checks if an element exists in a database table.
	 * @param tableName String, name of the database table to be queried.
	 * @param idfieldName String, name of the internal identifier field
	 * of the table.
	 * @param idElement Object, value of the element to be checked.
	 * @return boolean, True if the element is part of the queried table;
	 * False in any other case. 
	 * @throws ExplicaException, in case any error ocurrs during the query.
	 */
	public boolean existsElement(String tableName, String idfieldName, Object idElement) throws ExplicaException {
		boolean result = false;

		// Open a new Hibernate session to query the Database
		Session session = HibernateUtil.getSessionFactory().openSession();
		
		SQLGenerator sqlGen = new SQLGenerator();
		
		String sqlQuery = null;

        try {
        	// Create the list of fields to include in the resulting query
        	ArrayList lFields = new ArrayList();
        	lFields.add(idfieldName);
        	
        	CriteriaBean criteria = new CriteriaBean();
        	criteria.setFieldId(idfieldName);
        	criteria.setFieldValue(idElement);
        	criteria.setFieldOperator(InterfaceDB.SQL_OPERATOR_EQUAL);
        	
        	ArrayList lCriteria = new ArrayList();
        	lCriteria.add(criteria);
        	
        	// Run the query and get the resulting elements
        	sqlQuery = sqlGen.getSQLQuery(tableName, lFields, lCriteria, null);
        	Object objQueried = session.createSQLQuery(sqlQuery).
        		uniqueResult();
        	
        	result = objQueried != null;
        	
            System.out.println( "Consulta realizada! " +
            		(result == false?(" No se ha encontrado ningún elemento!"):
            		("Se ha encontrado: el elemento!")));
        }
        catch (HibernateException ex) {
        	ArrayList lParams = new ArrayList();
        	lParams.add(sqlQuery);
        	ResultMessage msg = msgCatalog.newResultMessage(InterfaceErrors.ERR_DB_QUERY_ERROR, ex, lParams);
        	throw new ExplicaException(msg);
        }
        
        // Close the Hibernate session
        session.close();
        
		return result;
	}
	
	/**
	 * Returns tag Id assigned to CVS source file.
	 */
	public static String getRevision() {
		return "$Id: BaseDAO.java,v 1.1 2008-03-18 12:58:46 mario Exp $";
	}
}
